search or find string fucntion.

Hi,

I have to compare requirements(object Text) across two modules and find the duplicate requirements.
I'm able to do that by using for loops. But it is taking lot of time as the modules are very huge.

Instead of iterating through loops, is there any function (or script) available for finding or searching string directly?

Thanks,
Naveen
SystemAdmin - Fri May 13 04:00:02 EDT 2011

Re: search or find string fucntion.
Peter_Albert - Fri May 13 04:37:05 EDT 2011

Hi Naveen,

the tool of choice for identifying duplications is always a Skip list. It is populated fast, and finding elements is fast as well. The script below populates such a skip list for two consecutive modules. It stores the Object Text as Key, and the module name and Object Absolute Number as key. For each object, it checks if the key (the text) exists, and prints a message. If it does not exist yet, it is added to the list. Thereby the script also identified possible duplications within one module. The printed message contains both module names, so duplications within one, and between the two modules, can be distinguished easily.

You only have to add the two paths to your modules, and your criterion for a requirement.

Regards,

Peter
 

pragma runLim, 0
string module_1 = "<path to the first module>"
string module_2 = "<path to the secondmodule>"
Skip sList      = createString
Module mod 
// ------------------------------------------------------------------------
void duplicates(Module mod)
{ // Search for duplicate Object Text
  string sKey, sValue
  Object obj
  for obj in entire mod do 
  { // Loop through first module
    if (isDeleted obj){continue}
    if (table obj)    {continue}
    if (row obj)      {continue}
    if (cell obj)     {continue}
 
    // Add your decision criteria for requirements below
    //if (!isRequirement(obj)){continue}
 
    sKey = probeAttr_(obj, "Object Text")
    if (sKey == "")   {continue}
    if (find(sList, sKey, sValue))
    { // Duplicate within first module
      print "Duplicate Text in  " (name mod) " #" obj."Absolute Number" " and " sValue ": " sKey [0:30] "...\n"
    } // Duplicate within first module
    else
    { // Unique text so far
      sValue = (name mod)  " # " obj."Absolute Number" ""
      put(sList, sKey, sValue)
    } // Unique text so far
  } // Loop through first module
} // Search for duplicate Object Text
// ------------------------------------------------------------------------
mod = read(module_1)
duplicates(mod)
mod = read(module_2)
duplicates(mod)
delete sList

Re: search or find string fucntion.
Mathias Mamsch - Fri May 13 04:56:06 EDT 2011

Why are you looking for duplicate requirements? If you will just look for duplicate text, you are probably not getting what you want. A single whitespace, somebody inserting a comma, etc. will break the comparison. Also if for example in your huge module you have 100 tables that all have the same heading lines, you are pretty much out of luck. You will be getting a lot of 'false positives'.

Are you trying to matchup two related modules? If you tell us a little more about what you are trying to accomplish and why, we might be able to help you even more. Regards, Mathias

Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Re: search or find string fucntion.
SystemAdmin - Fri May 13 07:14:43 EDT 2011

Mathias Mamsch - Fri May 13 04:56:06 EDT 2011
Why are you looking for duplicate requirements? If you will just look for duplicate text, you are probably not getting what you want. A single whitespace, somebody inserting a comma, etc. will break the comparison. Also if for example in your huge module you have 100 tables that all have the same heading lines, you are pretty much out of luck. You will be getting a lot of 'false positives'.

Are you trying to matchup two related modules? If you tell us a little more about what you are trying to accomplish and why, we might be able to help you even more. Regards, Mathias


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Hi Mathias,
Yes I understand that there are limititations in string comparision. A small whitespace, comma etc will break the comparision. Also I'm not considering objects with OLEs. Before comparision I'll trim the leading and trailing spaces.

These two modules are basically the top level modules and we found there are duplicate requirements. We want to make sure that there is no redundancy.

Meanwhile I'll explore the skiplist thing which Peter mentioned.

Thanks,
Naveen

Re: search or find string fucntion.
llandale - Mon May 16 14:44:59 EDT 2011

SystemAdmin - Fri May 13 07:14:43 EDT 2011
Hi Mathias,
Yes I understand that there are limititations in string comparision. A small whitespace, comma etc will break the comparision. Also I'm not considering objects with OLEs. Before comparision I'll trim the leading and trailing spaces.

These two modules are basically the top level modules and we found there are duplicate requirements. We want to make sure that there is no redundancy.

Meanwhile I'll explore the skiplist thing which Peter mentioned.

Thanks,
Naveen

Random thoughts.
[1] I cannot think of a mechanism for looking at the text of the requirement, noting the key words, then searching other requiremetns for those Key Words. e.g. if you see requiement "The System shall provide Small Boats" then you want to find all other "Small Boats" requirements. Perhaps "key words" are other than verbs and other than standard words like "The" "System" "shall" "the" "an" etc.

[2] I wonder of function "string soundex(string)" could be useful here.

[3] Perhaps we can bypass routine edit tweaking by replacing all the routine characters with nothing. e.g. Turn "The System shall do 145; when active." into "TheSystemshalldo145whenactive". It turns out I've done that already:

string ReplaceTheseChars =
" \t\n\v\f\r" charOf(160) ".,;:'?!-=~/" "()[]{}" "\"" "\\" //-
charOf(133) charOf(145) charOf(146) charOf(147) charOf(148) charOf(150) charOf(151) charOf(161) charOf(191) ""
 
Buffer    gl_fReplace_ResultsBuff = create(),   // use before calls to flReplaceString  -
        gl_fReplace_ToStngBuff  = create()      // Houses ToString, allows quick Combine
 
 
//***************************
void    fReplaceCharacters(Buffer &in_buf, string in_Characters, in_ReplaceString)
{     // Replace each character foundin the input buffer, with the Replace String.
        if (null in_buf         or 
            null in_buf[0]      or 
            null in_Characters) return  // Nothing to do
 
        int     i, j
        char    c
        bool    Found
 
        gl_fReplace_ToStngBuff  = in_ReplaceString      // Combining Buffers is more efficient than appending Strings.
        gl_fReplace_ResultsBuff = ""
 
        for (i=0; i<length(in_buf); i++)
        {  c  = in_buf[i]
           Found        = false
           for (j=0; j<length(in_Characters); j++)
           {  if (c == in_Characters[j])
              {  Found        = true
                 break
              }
           }  // end for each in_Characters
           if (Found)   //-
           then combine(gl_fReplace_ResultsBuff, gl_fReplace_ToStngBuff, 0)     // Replace the character
           else gl_fReplace_ResultsBuff += c                                            // Preserve the Character
        }     // end for every character in in_buf.
 
        in_buf  = ""                  // Replace the results
        combine(in_buf, gl_fReplace_ResultsBuff, 0)
 
}     // end fReplaceCharacters(Buffer)
 
Buffer bufText = create()
bufText = probeAttr_(obj, "Object Text")
print "From>>>>\n"
print tempStringOf(bufText)
print "\n"
        fReplaceCharacters(bufText, ReplaceTheseChars, "")
print "After>>>\n"
print tempStringOf(bufText)

 

This is my code that defines these characters and provides some explanation for what they are, for whatever that's worth:
        // code 160 is an MS-Word non-breaking space.
const string    cl_White        = " \t\n\v\f\r" charOf(160) ""      // White Space.
 
// Punctuation, as defined here: http://www.merriam-webster.com/table/dict/punctuat.htm
const string    cl_Punct = ".,;:'?!-=~/" // Normal                Typeable        -
                        "()[]{}"    // paired braces        -
                        "\""             // double quote         -
                        "\\"          // back slash           -
                        charOf(133)     // ellipsis  ...         Non-Typeable   -
                        charOf(145)     // open  single quote-
                        charOf(146)     // close single quote   -
                        charOf(147)     // open  double quote   -
                        charOf(148)     // close double quote   -
                        charOf(150)     // 'en' dash            -
                        charOf(151)     // 'em' dash            -
                        charOf(161)     // upside down exclamation point (Spanish)      -
                        charOf(191)     // upside down question (Spanish)               -
                        ""

 

 

  • Louie

 

Re: search or find string fucntion.
llandale - Mon May 16 15:00:04 EDT 2011

llandale - Mon May 16 14:44:59 EDT 2011

Random thoughts.
[1] I cannot think of a mechanism for looking at the text of the requirement, noting the key words, then searching other requiremetns for those Key Words. e.g. if you see requiement "The System shall provide Small Boats" then you want to find all other "Small Boats" requirements. Perhaps "key words" are other than verbs and other than standard words like "The" "System" "shall" "the" "an" etc.

[2] I wonder of function "string soundex(string)" could be useful here.

[3] Perhaps we can bypass routine edit tweaking by replacing all the routine characters with nothing. e.g. Turn "The System shall do 145; when active." into "TheSystemshalldo145whenactive". It turns out I've done that already:

string ReplaceTheseChars =
" \t\n\v\f\r" charOf(160) ".,;:'?!-=~/" "()[]{}" "\"" "\\" //-
charOf(133) charOf(145) charOf(146) charOf(147) charOf(148) charOf(150) charOf(151) charOf(161) charOf(191) ""
 
Buffer    gl_fReplace_ResultsBuff = create(),   // use before calls to flReplaceString  -
        gl_fReplace_ToStngBuff  = create()      // Houses ToString, allows quick Combine
 
 
//***************************
void    fReplaceCharacters(Buffer &in_buf, string in_Characters, in_ReplaceString)
{     // Replace each character foundin the input buffer, with the Replace String.
        if (null in_buf         or 
            null in_buf[0]      or 
            null in_Characters) return  // Nothing to do
 
        int     i, j
        char    c
        bool    Found
 
        gl_fReplace_ToStngBuff  = in_ReplaceString      // Combining Buffers is more efficient than appending Strings.
        gl_fReplace_ResultsBuff = ""
 
        for (i=0; i<length(in_buf); i++)
        {  c  = in_buf[i]
           Found        = false
           for (j=0; j<length(in_Characters); j++)
           {  if (c == in_Characters[j])
              {  Found        = true
                 break
              }
           }  // end for each in_Characters
           if (Found)   //-
           then combine(gl_fReplace_ResultsBuff, gl_fReplace_ToStngBuff, 0)     // Replace the character
           else gl_fReplace_ResultsBuff += c                                            // Preserve the Character
        }     // end for every character in in_buf.
 
        in_buf  = ""                  // Replace the results
        combine(in_buf, gl_fReplace_ResultsBuff, 0)
 
}     // end fReplaceCharacters(Buffer)
 
Buffer bufText = create()
bufText = probeAttr_(obj, "Object Text")
print "From>>>>\n"
print tempStringOf(bufText)
print "\n"
        fReplaceCharacters(bufText, ReplaceTheseChars, "")
print "After>>>\n"
print tempStringOf(bufText)

 

This is my code that defines these characters and provides some explanation for what they are, for whatever that's worth:
        // code 160 is an MS-Word non-breaking space.
const string    cl_White        = " \t\n\v\f\r" charOf(160) ""      // White Space.
 
// Punctuation, as defined here: http://www.merriam-webster.com/table/dict/punctuat.htm
const string    cl_Punct = ".,;:'?!-=~/" // Normal                Typeable        -
                        "()[]{}"    // paired braces        -
                        "\""             // double quote         -
                        "\\"          // back slash           -
                        charOf(133)     // ellipsis  ...         Non-Typeable   -
                        charOf(145)     // open  single quote-
                        charOf(146)     // close single quote   -
                        charOf(147)     // open  double quote   -
                        charOf(148)     // close double quote   -
                        charOf(150)     // 'en' dash            -
                        charOf(151)     // 'em' dash            -
                        charOf(161)     // upside down exclamation point (Spanish)      -
                        charOf(191)     // upside down question (Spanish)               -
                        ""

 

 

  • Louie

 

More incomplete random thoughts:
[4] Get the text, break it up into words, and stick the word along with the Object into a skip list. Report each word along with each Object's text that uses it. let the user decide which "words" are useful "key words" by ignoring the others.

Have list of words to ignore like "Shall" and "System" and "the". During the report, first count the number of objects with a particul word, and just go ahead and ignore words that are referenced by lots of objects, perhaps 6 or more; such words are obviously not "key" if many objects refer to them.


Skip skpWords 
// KEY 'string' a word found in the text; DATA: 'Skip' of objects with that word 
//Skip skpObjects // This skip list is the 'DATA' for skpWords. 
// KEY 'Object'; DATA: 'string' Text of that object   

void InsertKeyWord(string KeyWord, Object obj) 
{  
// Insert the key word into the global skips Skip  skpObjects 

if (!find(skpWords, KeyWord, skpObjects)) 
{    
// First encounter with this KeyWord skpObjects = create put(skpWords, KeyWord, skpObjects) 
} put(skpObjects, obj, probeAttr_(obj, 
"Object Text")) 
}  
// end InsertKeyWord()     

void DumpSkips() 
{   Skip skpObjects string KeyWord, ObjID Object obj Buffer bufResults = create()   

for skpObjects in skpWords 

do 
{  KeyWord = (string key skpWords) bufResults += 
"\n" bufResults += KeyWord 

for Text in skpObjects 

do 
{  obj = (Object key skpObjects) ObjID = identifier(obj) bufResults += 
"\n\t" bufResults += Text 
} 
} print tempStringOf(bufResults) delete(bufResults) 
}

  • Louie